package com.wl.tp;

import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Arrays;

import com.wl.tp.protocol.ByteTpMessage;
import com.wl.tp.protocol.NetInteger;
import com.wl.tp.protocol.TextTpMessage;

/**
 * Socket 收发器  通过Socket发送数据，并使用新线程监听socket接收到的数据
 * @author EDZ
 *
 */

public abstract class SocketTransceiver implements Runnable {
	
	protected Socket socket;
	protected InetAddress addr;
	protected DataInputStream in;
	protected DataOutputStream out;
	private boolean runFlag;
	
	
	public SocketTransceiver(Socket socket) {
		this.socket = socket;
		this.addr = socket.getInetAddress();
	}
	
	public InetAddress getInetAddress() {
		return addr;
	}
	
	/**
	 * 开启收发
	 * 如果是失败会断开连接并回调
	 */
	public void start() {
		runFlag = true;
		new Thread(this).start();
	}
	
	public void stop() {
		runFlag = false;
		try {
			socket.shutdownInput();
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public boolean send(String s) {
		if(out != null) {
			try {
				byte[] data = new TextTpMessage(s).encode();
				if(data != null) {
					out.write(data);
					out.flush();
				}
				return true;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return false;
	}
	
	public boolean send(byte[] msg) {
		if(out != null) {
		try {
			byte[] data = new ByteTpMessage(msg).encode();
			if(data != null) {
				out.write(data);
				out.flush();
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	return false;
		
	}
	
	/**
	 * 监听Socket接收的数据(新线程中运行)
	 */
	@Override
	public void run() {
		try {
			in = new DataInputStream(this.socket.getInputStream());
			out = new DataOutputStream(this.socket.getOutputStream());
		} catch (Exception e) {
			e.printStackTrace();
			runFlag = false;
		}
		
		while (runFlag) {
			try {
				byte[] lenData = new byte[4];
				in.read(lenData);
				NetInteger netlen = new NetInteger();
				netlen.parse(lenData, 0);
				int dataLen = netlen.getIntValue();
				System.out.println("收到数据包大小:" + dataLen);
				if(dataLen > 0) {
					byte[] buffer = new byte[dataLen];
					int offset = 0;
					int len = 0;
					int size = 0;
					if(in == null) {
						break;
					}
					while(len < dataLen) {
						size = in.read(buffer, offset + len, dataLen - offset - len);
						len += size;
					}
//					System.out.println("receive:" + Arrays.toString(buffer));
					this.onReceive(addr, buffer);
				} else {
					// 连接被断开(被动)
					runFlag = false;
				}
			} catch (Exception e) {
				//连接被断开（被动）
				e.printStackTrace();
				runFlag = false;
			}
		}
		
		//断开连接
		try {
			in.close();
			out.close();
			socket.close();
			in = null;
			out = null;
			socket = null;
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		this.onDisconnect(addr);
	}
	
	/**
	 * 接收到的数据
	 * 
	 * @param addr
	 * @param s
	 */
	public abstract void onReceive(InetAddress addr, byte[] data);
	
	public abstract void onDisconnect(InetAddress addr);
	
}
